package com.atguigu.gmall.serviceutil.service.impl;

import com.atguigu.gmall.common.util.JsonUtil;
import com.atguigu.gmall.serviceutil.service.CacheService;
import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author A
 * @version 1.0
 * @description: TODO
 * @date 2025/8/31 3:55
 */
@Service
public class CacheServiceImpl implements CacheService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    //从缓存中获取数据
    @Override
    public <T> T getCacheData(String cacheKey, TypeReference<T> typeReference) {
        //先从缓存中获取数据
        String jsonStr = redisTemplate.opsForValue().get(cacheKey);
        if (jsonStr == null) {
            //缓存中没有数据,走数据库查询
            return null;
        }
        if ("no".equals(jsonStr)) {
            //返回一个T类型的对象,但是数据为空
            if (typeReference.getType() instanceof Collection) {
                //如果是集合类型,返回一个空集合
                return JsonUtil.jsonToObject("[]", typeReference);
            } else {
                //如果是其他类型,返回空对象
                return JsonUtil.jsonToObject("{}", typeReference);
            }
        }
        //反序列化
        return JsonUtil.jsonToObject(jsonStr, typeReference);
    }

    //保存数据到缓存中
    @Override
    public void setCacheData(String cacheKey, Object object) {
        //从数据库查询数据为空时,保存一个"no"字符串到缓存中,防止缓存穿透
        if (object == null) {
            redisTemplate.opsForValue().set(cacheKey, "no", 30, TimeUnit.MINUTES);
        }
        //防止缓存雪崩,设置缓存过期时间为随机值,防止缓存击穿
        long randomTime = (long) ((Math.random() *1440)+1 ); //1-1440分钟
        redisTemplate.opsForValue().set(cacheKey, Objects.requireNonNull(JsonUtil.toStr(object)), randomTime, TimeUnit.MINUTES);
    }
}

